
package com.meixiaoliang.portal.modular.system.service.impl;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.meixiaoliang.portal.modular.system.dao.MenuMapper;
import com.meixiaoliang.portal.modular.system.model.Menu;
import com.meixiaoliang.portal.modular.system.model.constant.Constant;
import com.meixiaoliang.portal.modular.system.model.enums.BooleanEnum;
import com.meixiaoliang.portal.modular.system.model.enums.MenuTypeEnum;
import com.meixiaoliang.portal.modular.system.model.enums.RoleEnum;
import com.meixiaoliang.portal.modular.system.model.result.MenuListResult;
import com.meixiaoliang.portal.modular.system.model.vo.MenuLeftVo;
import com.meixiaoliang.portal.modular.system.service.MenuService;
import com.meixiaoliang.portal.modular.system.service.RoleMenuService;
import com.meixiaoliang.portal.modular.system.service.RoleService;

/**
 * 菜单
 *
 * @author mei.xiaoliang@qq.com
 */
@Service
public class MenuServiceImpl extends ServiceImpl<MenuMapper, Menu> implements MenuService {

    private Logger          logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    private MenuMapper      menuMapper;
    @Autowired
    private RoleMenuService roleMenuService;
    @Autowired
    private RoleService     roleService;

    @Override
    public List<Menu> listAll() {

        List<Menu> menulist = list();
        Collections.sort(menulist);

        List<Menu> resultList = new ArrayList<>();

        // 菜单级联拼接
        for (Menu menu : menulist) {
            if (0 == menu.getParent()) {
                Menu item = new Menu();
                BeanUtils.copyProperties(menu, item);
                item.setTypeValue(null == MenuTypeEnum.getByCode(item.getType()) ? "" : MenuTypeEnum.getByCode(item.getType()).getName());
                item.setStatusBoolean(BooleanEnum.TRUE.getCode() == menu.getStatus());
                item.setChildren(buildChildren(menu.getId(), menulist));
                resultList.add(item);
            }
        }

        return resultList;
    }

    @Override
    public List<MenuLeftVo> listSingleAll() {
        List<Menu> menulist = list();
        Collections.sort(menulist);

        List<MenuLeftVo> resultList = new ArrayList<>();

        // 菜单级联拼接
        for (Menu menu : menulist) {
            if (0 == menu.getParent()) {
                MenuLeftVo leftVo = new MenuLeftVo();
                leftVo.setId(menu.getId());
                leftVo.setName(menu.getName());
                leftVo.setUrl(menu.getUrl());
                leftVo.setIcon(menu.getIcon());
                leftVo.setChildren(buildChildren(menu.getId(), menulist, false));
                resultList.add(leftVo);
            }
        }

        return resultList;
    }

    @Override
    public MenuListResult listLeft(int userId) {

        // 管理员开放所有菜单
        List<Menu> menulist = null;
        if (Constant.ADMIN_ID == userId) {
            logger.debug("管理员显示所有菜单");
            menulist = menuMapper.selectList(new QueryWrapper<Menu>().eq("status", BooleanEnum.TRUE.getCode()));
        }
        // 非管理员仅开发角色对应菜单
        else {
            menulist = menuMapper.listLeft(userId, BooleanEnum.TRUE.getCode());
        }
        Collections.sort(menulist);

        List<MenuLeftVo> resultList = new ArrayList<>();

        for (Menu menu : menulist) {
            if (0 == menu.getParent()) {
                MenuLeftVo leftVo = new MenuLeftVo();
                leftVo.setId(menu.getId());
                leftVo.setName(menu.getName());
                leftVo.setUrl(menu.getUrl());
                leftVo.setChildren(buildChildren(menu.getId(), menulist, true));
                resultList.add(leftVo);
            }
        }

        // 面包屑，请求路由、返回值映射
        Map<String, Map<String, Object>> menuBreadMap = new HashMap<>();

        for (MenuLeftVo parent : resultList) {
            List<MenuLeftVo> firstChildren = parent.getChildren();
            for (MenuLeftVo item : firstChildren) {
                if (0 == item.getChildren().size()) {
                    Map<String, Object> map = new HashMap<>();
                    // 二级菜单、面包屑数据构建
                    List<MenuLeftVo> breadStringList = new ArrayList<>();
                    breadStringList.add(new MenuLeftVo().setId(parent.getId()).setName(parent.getName()));
                    breadStringList.add(new MenuLeftVo().setId(item.getId()).setName(item.getName()));
                    map.put("bread", breadStringList);
                    map.put("name", item.getName());
                    menuBreadMap.put(item.getUrl(), map);
                } else {
                    // TODO 若有 3 级菜单，请在这里添加
                }
            }
        }

        MenuListResult result = new MenuListResult().setMenuLeftVoList(resultList).setMenuBreadMap(menuBreadMap);

        return result;
    }

    @Override
    public List<String> listPermissionByUserId(int userId) {

        List<String> resultList;
        List<Integer> roleIdList = roleService.listIdByUserId(userId);

        if (roleIdList.contains(RoleEnum.ADMIN.getCode())) {
            logger.info("管理员找权限");
            resultList = menuMapper.listAdminPermission(BooleanEnum.TRUE.getCode());
        } else {
            resultList = menuMapper.listPermission(userId, BooleanEnum.TRUE.getCode());
        }

        return resultList;
    }

    //
    //    /**
    //     * @see com.meixiaoliang.service.MenuService#get(int)
    //     */
    //    @Override
    //    public Menu get(int menuId) {
    //        return menuDao.get(menuId);
    //    }
    //
    //    /**
    //     * @see com.meixiaoliang.service.MenuService#insert(com.meixiaoliang.entity.Menu)
    //     */
    //    @Override
    //    public int insert(Menu menu) {
    //        return menuDao.insert(menu);
    //    }
    //
    //    /**
    //     * @see com.meixiaoliang.service.MenuService#update(com.meixiaoliang.entity.Menu)
    //     */
    //    @Override
    //    public int update(Menu menu) {
    //        return menuDao.update(menu);
    //    }
    //
    //    /**
    //     * @see com.meixiaoliang.service.MenuService#updateRoleRule(java.lang.Integer, int[])
    //     */
    //    @Override
    //    public void updateRoleRule(Integer roleId, int[] selectIds) {
    //        roleMenuDao.delete(roleId);
    //        roleMenuDao.insertBatch(roleId, selectIds);
    //    }
    //
    //    /**
    //     * @see com.meixiaoliang.service.MenuService#delete(int)
    //     */
    //    @Override
    //    public int delete(int menuId) {
    //        return menuDao.delete(menuId);
    //    }

    private List<Menu> buildChildren(int parent, List<Menu> menulist) {

        List<Menu> resultList = new ArrayList<>();

        for (Menu menu : menulist) {
            if (parent == menu.getParent()) {
                Menu item = new Menu();
                BeanUtils.copyProperties(menu, item);
                item.setTypeValue(null == MenuTypeEnum.getByCode(item.getType()) ? "" : MenuTypeEnum.getByCode(item.getType()).getName());
                item.setStatusBoolean(BooleanEnum.TRUE.getCode() == menu.getStatus());
                item.setChildren(buildChildren(menu.getId(), menulist));
                resultList.add(item);
            }
        }

        if (0 == menulist.size() || 0 == resultList.size()) {
            return null;
        }

        return resultList;
    }

    /**
     * 菜单构建下级
     *
     * @param parent   菜单顶级节点
     * @param menulist 所有菜单
     * @param all
     * @return
     */
    private List<MenuLeftVo> buildChildren(int parent, List<Menu> menulist, boolean all) {

        List<MenuLeftVo> resultList = new ArrayList<>();

        for (Menu menu : menulist) {
            if (parent == menu.getParent()) {
                MenuLeftVo leftVo = new MenuLeftVo();
                leftVo.setId(menu.getId());
                leftVo.setName(menu.getName());
                leftVo.setUrl(menu.getUrl());
                leftVo.setIcon(menu.getIcon());
                leftVo.setChildren(buildChildren(menu.getId(), menulist, all));
                resultList.add(leftVo);
            }
        }

        if (0 == menulist.size()) {
            return null;
        }

        return resultList;
    }

}
